#pragma once
#include <sstream>
#include <vector>
#include <string>
#include <fstream>
#include <tchar.h>

using namespace std;

class Utils 
{
public:
	template <class T>
	static string ToString(const T& t, int prec = 2)
	{
		stringstream ss;
		ss.precision(prec);
		ss << fixed << t;
		return ss.str();
	}

	template <class T>
	static bool FromString(T& t, const string& s, ios_base& (*f)(ios_base&))
	{
		istringstream iss(s);
		return !(iss >> f >> t).fail();
	}

	static int xtoi(const TCHAR *value)
	{
		struct CHexMap
		{
			TCHAR chr;
			int value;
		};
		const int HexMapL = 16;
		CHexMap HexMap[HexMapL] =
		{
			{'0', 0}, {'1', 1},
			{'2', 2}, {'3', 3},
			{'4', 4}, {'5', 5},
			{'6', 6}, {'7', 7},
			{'8', 8}, {'9', 9},
			{'A', 10}, {'B', 11},
			{'C', 12}, {'D', 13},
			{'E', 14}, {'F', 15}
		};
#define _SCL_SECURE_NO_WARNINGS

		TCHAR *mstr = _tcsupr(_tcsdup(value));
		TCHAR *s = mstr;
		int result = 0;
		if (*s == '0' && *(s + 1) == 'X') s += 2;
		bool firsttime = true;
		while (*s != '\0')
		{
			bool found = false;
			for (int i = 0; i < HexMapL; i++)
			{
				if (*s == HexMap[i].chr)
				{
					if (!firsttime) result <<= 4;
					result |= HexMap[i].value;
					found = true;
					break;
				}
			}
			if (!found) break;
			s++;
			firsttime = false;
		}
		free(mstr);
		return result;
	}




	template <typename IntegerType>
	static IntegerType BytesToInt(byte *bytes, bool little_endian = true)
	{
		IntegerType result = 0;

		if (little_endian)
			for (int n = sizeof( result ); n >= 0; n--)
				result = (result << 8) +bytes[ n ];
		else
			for (unsigned n = 0; n < sizeof( result ); n++)
				result = (result << 8) +bytes[ n ];
		return result;
	}


	static std::vector<std::string> &Split(const std::string &s, char delim, std::vector<std::string> &elems) {
		std::stringstream ss(s);
		std::string item;
		while(std::getline(ss, item, delim)) {
			elems.push_back(item);
		}
		return elems;
	}


	static std::vector<std::string> Split(const std::string &s, char delim) {
		std::vector<std::string> elems;
		return Split(s, delim, elems);
	}

	static void Log(const char *filename, const char *fmt)
	{
		bool iowrited = 1;
		ofstream outData;
		outData.open(filename, ios::app);
		outData << fmt;
		outData.close();
	}

	static void EraseLog(const char *filename)
	{
		ofstream outData;
		outData.open(filename);
		outData << "";
		outData.close();
	}
};